import logging
import copy
from datetime import datetime
from common.timeutil import get_interval_end_pair
from common.es_core.user_filter import UserFilter
from event_rule.dwc.user_event_rule.active_user_analysis import ACTIVE_USER_ANALYSIS_CONFIG
from common.es_core.report_creator import ReportCreator, UserReportCreator
from common.mg_core.mg import get_report_template, insert_or_update, get_report
from common.account import db as account_db
from .const import GAME_DCT

_LOGGER = logging.getLogger(__name__)


def active_user_analysis_handler(interval_type, base_time, last_window, event_name, event_rule, index):
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    base_user_pool = None
    collection = '_'.join(['user', event_name, 'report'])
    user_analysis_report = ReportCreator.create_report(user_pool=base_user_pool, start_time=start_time,
                                                       end_time=end_time, event_rule=event_rule, index=index,
                                                       custom_not_filter=[{'term': {"bet_order_user_type": 1}}],
                                                       max_bucket=40000, to_group=True)
    user_id_list = [user_report['_user_id'] for user_report in user_analysis_report['list']]
    users, _ = account_db.list_user(index, {'user_id__in': user_id_list}, disable_paginate=True)
    user_dct = {str(user['user_id']): user for user in users}
    for user_report in user_analysis_report['list']:
        report_id = '-'.join([str(start_time).split(' ')[0], interval_type.value, str(user_report['_user_id'])])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        user = user_dct.get(str(user_report['_user_id']), {})
        user_report['chn'] = user.get('channel', '未知')
        user_report['last_active_channel'] = user_report['last_active_channel'].get(
            ''
            '_source', {}).get('_chn', user.get('channel', '未知'))
        user_report['registered_at'] = str(user.get('registered_at', '未知'))
        report_template.update(user_report)
        insert_or_update(report_template, database=index, collection=collection)


def _get_user_pay_ability_report_dynamic_argument_dct(start_time, end_time, recharge_stage, index):
    # 充值用户
    user_filter = UserFilter(merchant_name=index)
    if recharge_stage[0] is not None and recharge_stage[1] is not None:
        user_filter.stage_filter('recharge', 'recharge_price', 'sum', start_time, end_time,
                                 recharge_stage[0], recharge_stage[1])
    elif recharge_stage[1] is not None:
        user_filter.stage_filter(['recharge', 'active'], 'recharge_price', 'sum', start_time, end_time,
                                 recharge_stage[0], recharge_stage[1])
    else:
        user_filter.event_user_filter('recharge', start_time, end_time)
    recharge_user_pool = user_filter.get_user_pool()
    # 充值且参与用户
    user_filter = UserFilter(recharge_user_pool, merchant_name=index)
    user_filter.event_user_filter(['bet_order'], start_time, end_time)
    recharge_bet_user_pool = user_filter.get_user_pool()
    # 充值且中奖用户
    user_filter = UserFilter(recharge_user_pool, merchant_name=index)
    user_filter.event_user_filter(['bet_order'], start_time, end_time, custom_filter=[
        {"bool": {"should": [
            {"range": {"bet_order_award_amount": {"gt": 0}}}
        ]}}])
    recharge_win_user_pool = user_filter.get_user_pool()
    # 充值且盈利用户
    user_filter = UserFilter(recharge_user_pool, merchant_name=index)
    user_filter.stage_filter(['bet_order'],
                             ['bet_order_award_amount', '-bet_order_bet_amount'],
                             'sum', start_time, end_time, 0)
    recharge_profit_user_pool = user_filter.get_user_pool()
    # 充值且亏损用户
    user_filter = UserFilter(recharge_user_pool, merchant_name=index)
    user_filter.stage_filter(['bet_order'],
                             ['bet_order_award_amount', '-bet_order_bet_amount'],
                             'sum', start_time, end_time, None, 0)
    recharge_lose_user_pool = user_filter.get_user_pool()
    dynamic_target_users_dct = dict(
        recharge_users=recharge_user_pool,
        recharge_bet_users=recharge_bet_user_pool,
        recharge_win_users=recharge_win_user_pool,
        recharge_profit_users=recharge_profit_user_pool,
        recharge_lose_users=recharge_lose_user_pool
    )
    return dynamic_target_users_dct


def user_pay_ability_report_handler(interval_type, base_time, last_window, event_name, event_rule, index):
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    collection = '_'.join(['user', event_name, 'report'])
    recharge_stages = ['NoRecharge', (0, 10), (10, 100), (100, 1000), (1000, 5000),
                       (5000, 10000), (10000, 100000), 'ALL']
    for recharge_stage in recharge_stages:
        if recharge_stage == 'ALL':
            recharge_stage = (None, None,)
            _id = '-'.join(['all', str(start_time).split(' ')[0]])
            stage, key = 'all', '汇总'
        elif recharge_stage == 'NoRecharge':
            recharge_stage = (None, 0,)
            _id = '-'.join(['0', str(start_time).split(' ')[0]])
            stage, key = 'others', '未充值'
        else:
            _id = '-'.join(['-'.join([str(recharge_stage[0]), str(recharge_stage[1])]), str(start_time).split(' ')[0]])
            stage, key = str(recharge_stage[0]), '-'.join([str(recharge_stage[0]), str(recharge_stage[1])])
        dynamic_target_users_dct = _get_user_pay_ability_report_dynamic_argument_dct(
            start_time, end_time, list(recharge_stage), index=index
        )
        custom_filter = [{"terms": {"_user_id": dynamic_target_users_dct['recharge_users']}}]
        pay_ability_report = UserReportCreator.create_user_report(
            start_time=start_time, end_time=end_time, event_rule=event_rule, index=index,
            custom_filter=custom_filter, dynamic_argument_dct=dynamic_target_users_dct, to_group=True, sum_up=True)
        report_id = '-'.join(['all', _id, interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        report_template.update({event_rule.get('group_by').replace('.keyword', ''): 'all', 'key': key,
                                'recharge_stage': stage})
        report_template.update(pay_ability_report['sum_up'])
        insert_or_update(report_template, database=index, collection=collection)
        for report in pay_ability_report['list']:
            report_id = '-'.join([report[event_rule.get('group_by').replace('.keyword', '')], _id, interval_type.value])
            report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
            report_template['key'], report_template['recharge_stage'] = key, stage
            report_template.update(report)
            insert_or_update(report_template, database=index, collection=collection)


def new_user_report_handler(interval_type, base_time, last_window, event_name, event_rule, index='loki'):
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    user_pool = None
    collection = '_'.join(['user', event_name, 'report'])
    report_template = get_report_template(start_time, interval_type)
    report_template.update(ReportCreator.create_report(user_pool=user_pool, start_time=start_time, end_time=end_time,
                                                       event_rule=event_rule, index=index))
    report_template.update({event_rule.get('group_by').replace('.keyword', ''): 'all'})
    insert_or_update(report_template, database=index, collection=collection)
    new_user_reports = ReportCreator.create_report(user_pool=user_pool, start_time=start_time, end_time=end_time,
                                                   event_rule=event_rule, index=index, to_group=True)
    for report in new_user_reports['list']:
        report_id = '-'.join([report[event_rule.get('group_by').replace('.keyword', '')],
                              str(start_time).split(' ')[0], interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        report_template.update(report)
        insert_or_update(report_template, database=index, collection=collection)


def _get_new_user_report_dynamic_argument_dct(index, start_time, end_time):
    # 活跃用户
    user_filter = UserFilter(merchant_name=index)
    user_filter.event_user_filter(['bet_order'], start_time, end_time,
                                  custom_not_filter={"term": {"bet_order_user_type": 1}})
    bet_user_pool = user_filter.get_user_pool()
    # 注册用户
    user_filter = UserFilter(merchant_name=index)
    user_filter.event_user_filter(['bind'], start_time, end_time)
    register_user_pool = user_filter.get_user_pool()
    # 活跃用户
    user_filter = UserFilter(merchant_name=index)
    user_filter.stage_filter(['bet_order', 'recharge'],
                             ['recharge_price'],
                             'value_count', start_time, end_time, None, 0,
                             custom_not_filter={"term": {"bet_order_user_type": 1}})
    free_bet_user_pool = user_filter.get_user_pool()
    # 付费用户
    user_filter = UserFilter(merchant_name=index)
    user_filter.event_user_filter(['recharge'], start_time, end_time)
    recharge_user_pool = user_filter.get_user_pool()
    # 一次付费用户
    user_filter = UserFilter(merchant_name=index)
    user_filter.stage_filter(['recharge'], 'recharge_price', 'value_count', start_time, end_time, 0, 1)
    one_recharge_user_pool = user_filter.get_user_pool()
    # 多次付费用户
    user_filter = UserFilter(merchant_name=index)
    user_filter.stage_filter(['recharge'], 'recharge_price', 'value_count', start_time, end_time, 1, None)
    multi_recharge_user_pool = user_filter.get_user_pool()
    # 玩法盈利用户
    user_filter = UserFilter(merchant_name=index)
    user_filter.stage_filter(['bet_order'],
                             ['bet_order_award_amount', '-bet_order_bet_amount'],
                             'sum', start_time, end_time, 0, custom_not_filter={"term": {"bet_order_user_type": 1}})
    win_user_pool = user_filter.get_user_pool()
    # 玩法亏损用户
    user_filter = UserFilter(merchant_name=index)
    user_filter.stage_filter(['bet_order'],
                             ['bet_order_award_amount', '-bet_order_bet_amount'],
                             'sum', start_time, end_time, None, 0,
                             custom_not_filter={"term": {"bet_order_user_type": 1}})
    lose_user_pool = user_filter.get_user_pool()
    dynamic_target_users_dct = dict(
        register_user_1=register_user_pool,
        bet_order_user_1=bet_user_pool,
        free_bet_stay_user_1=free_bet_user_pool,
        recharge_stay_user_1=recharge_user_pool,
        one_recharge_stay_user_1=one_recharge_user_pool,
        multi_recharge_stay_user_1=multi_recharge_user_pool,
        win_stay_user_1=win_user_pool,
        lose_stay_user_1=lose_user_pool
    )
    return dynamic_target_users_dct


def new_user_stay_report_handler(interval_type, base_time, last_window, event_name, event_rule, index):
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    collection = '_'.join(['user', event_name, 'report'])
    dynamic_argument_dct = _get_new_user_report_dynamic_argument_dct(index, start_time, end_time)
    new_user_reports = UserReportCreator.create_user_report(
        start_time=start_time, end_time=end_time, event_rule=event_rule, index=index,
        dynamic_argument_dct=dynamic_argument_dct, to_group=True, sum_up=True)
    report_template = get_report_template(start_time, interval_type)
    report_template.update({event_rule.get('group_by').replace('.keyword', ''): 'all'})
    report_template.update(new_user_reports['sum_up'])
    insert_or_update(report_template, database=index, collection=collection)
    for report in new_user_reports['list']:
        report_id = '-'.join([report[event_rule.get('group_by').replace('.keyword', '')],
                              str(start_time).split(' ')[0], interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        report_template.update(report)
        insert_or_update(report_template, database=index, collection=collection)


def continuous_recharge_report_handler(interval_type, base_time, last_window, event_name, event_rule, index):
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    user_pool = None
    collection = '_'.join(['user', event_name, 'report'])
    report_template = get_report_template(start_time, interval_type)
    report_template.update(ReportCreator.create_report(user_pool=user_pool, start_time=start_time, end_time=end_time,
                                                       event_rule=event_rule, index=index))
    report_template.update({event_rule.get('group_by').replace('.keyword', ''): 'all'})
    insert_or_update(report_template, database=index, collection=collection)
    new_user_reports = ReportCreator.create_report(user_pool=user_pool, start_time=start_time, end_time=end_time,
                                                   event_rule=event_rule, index=index, to_group=True)
    for report in new_user_reports['list']:
        report_id = '-'.join([report[event_rule.get('group_by').replace('.keyword', '')],
                              str(start_time).split(' ')[0], interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        report_template.update(report)
        insert_or_update(report_template, database=index, collection=collection)


def get_active_user_analysis_report(index, user_id=None, chn_filter_list=None, time_range=None, disable_paginate=None,
                                    recharge_amount_max=None, recharge_amount_min=None, registered_time_range=None,
                                    sort_by=None, page=None, size=None, display_dimension=None):
    result_condition = dict()
    if recharge_amount_max or recharge_amount_min:
        result_condition.setdefault('recharge', {})
        if recharge_amount_min:
            result_condition['recharge']['$gte'] = recharge_amount_min
        if recharge_amount_max:
            result_condition['recharge']['$lte'] = recharge_amount_max
    condition = dict()
    if user_id:
        condition['_user_id'] = user_id
    if chn_filter_list:
        condition['chn'] = {'$in': chn_filter_list}
    condition['day'] = {'$gte': datetime.strftime(time_range[0], "%Y-%m-%d"),
                        '$lte': datetime.strftime(time_range[1], "%Y-%m-%d")}
    condition['registered_at'] = {'$gte': datetime.strftime(registered_time_range[0], '%Y-%m-%d %H:%M:%S'),
                                  '$lte': datetime.strftime(registered_time_range[1], '%Y-%m-%d %H:%M:%S')}
    (collection, event_rule) = ('user_active_user_analysis_report', ACTIVE_USER_ANALYSIS_CONFIG)
    custom_group_by_field = {
        'registered_at': {"$first": '$registered_at'},
        'chn': {"$first": "$chn"},
        '_user_id': {"$first": "$_user_id"}
    }
    custom_value_by_field = None
    if not display_dimension and datetime.strftime(time_range[0], "%Y-%m-%d") != datetime.strftime(time_range[1],
                                                                                                   "%Y-%m-%d"):
        custom_value_by_field = {"day": "汇总"}
    merge_report = True
    if display_dimension:
        merge_report = False
    analysis_result, total_count = get_report(index, collection, condition, sort_key=sort_by, page=page, size=size,
                                              disable_paginate=disable_paginate,
                                              custom_value_by_field=custom_value_by_field,
                                              merge_report=merge_report, event_rule=event_rule,
                                              group_key='_user_id', result_condition=result_condition,
                                              custom_group_by_field=custom_group_by_field, export_size_limit=40000)
    return analysis_result, total_count


def game_stage_analysis_handler(interval_type, base_time, last_window, event_name, event_rule, index):
    start_time, end_time = get_interval_end_pair(interval_type, base_time, last_window)
    game_stages = ['0', (0, 100), (100, 1000), (1000, 10000), (10000, 50000), (50000, 100000), (100000, 1000000), 'ALL']
    day = str(start_time).split(' ')[0]
    for game_stage in game_stages:
        if game_stage == 'ALL':
            game_stage = (None, None,)
            _id = '-'.join(['all', day])
            stage, key = 'all', '汇总'
        elif game_stage == '0':
            game_stage = (None, 0,)
            _id = '-'.join(['0', day])
            stage, key = 'others', "0"
        else:
            _id = '-'.join(['-'.join([str(game_stage[0]), str(game_stage[1])]), day])
            stage, key = str(game_stage[0]), '-'.join([str(game_stage[0]), str(game_stage[1])])

        report_id = '-'.join(['all', _id, day, interval_type.value])
        report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
        report_template.update(dict(game_id='all', game_name='汇总'))
        custom_not_filter = [{'term': {"bet_order_user_type": 1}}]
        _create_game_stage_report(index, start_time, end_time, custom_filter=[], custom_not_filter=custom_not_filter,
                                  event_rule=event_rule, base_report_template=report_template, game_stage=game_stage,
                                  stage=stage, key=key)
        for game_dct in GAME_DCT.get(index, []):
            game_id = game_dct.get('key')
            custom_filter = [{"term": {"bet_order_sub_type.keyword": game_id}}]
            report_id = '-'.join([game_id, _id, day, interval_type.value])
            report_template = get_report_template(start_time, interval_type, custom_report_id=report_id)
            report_template.update(dict(game_id=game_id, game_name=game_dct.get("name", "-")))
            _create_game_stage_report(index, start_time, end_time, custom_filter, custom_not_filter=custom_not_filter,
                                      event_rule=event_rule, base_report_template=report_template,
                                      game_stage=game_stage, stage=stage, key=key)


def _create_game_stage_report(index, start_time, end_time, custom_filter, custom_not_filter, event_rule,
                              base_report_template, game_stage, stage, key):
    collection = '_'.join(['user', 'game_stage', 'report'])
    dynamic_argument_dct = _get_game_stage_report_dynamic_argument_dct(
        index, start_time, end_time, list(game_stage), custom_filter, custom_not_filter
    )
    user_pool = dynamic_argument_dct['bet_user_pool']
    report_template = copy.deepcopy(base_report_template)
    game_stage_report = UserReportCreator.create_user_report(
        start_time=start_time, end_time=end_time, event_rule=event_rule, index=index, custom_filter=custom_filter,
        custom_not_filter=custom_not_filter, dynamic_argument_dct=dynamic_argument_dct, user_pool=user_pool
    )
    report_template.update({"bet_stage": stage, "key": key})
    report_template.update(game_stage_report)
    insert_or_update(report_template, database=index, collection=collection)


def _get_game_stage_report_dynamic_argument_dct(index, start_time, end_time, bet_stage, custom_filter,
                                                custom_not_filter):
    # 参与用户
    user_filter = UserFilter(merchant_name=index)
    if bet_stage[0] is not None and bet_stage[1] is not None:
        user_filter.stage_filter('bet_order', 'bet_order_real_bet_amount', 'sum', start_time, end_time,
                                 bet_stage[0], bet_stage[1], custom_filter=custom_filter,
                                 custom_not_filter=custom_not_filter)
    elif bet_stage[1] is not None:
        user_filter.stage_filter('bet_order', 'bet_order_real_bet_amount', 'sum', start_time, end_time,
                                 bet_stage[0], bet_stage[1], custom_filter=custom_filter,
                                 custom_not_filter=custom_not_filter)
    else:
        user_filter.event_user_filter('bet_order', start_time, end_time, custom_filter=custom_filter,
                                      custom_not_filter=custom_not_filter)
    bet_user_pool = user_filter.get_user_pool()
    # 参与且盈利用户
    user_filter = UserFilter(bet_user_pool, merchant_name=index)
    user_filter.stage_filter(['bet_order'],
                             ['bet_order_award_amount', '-bet_order_bet_amount'],
                             'sum', start_time, end_time, 0)
    profit_user_pool = user_filter.get_user_pool()
    # 参与且亏损用户
    user_filter = UserFilter(bet_user_pool, merchant_name=index)
    user_filter.stage_filter(['bet_order'],
                             ['bet_order_award_amount', '-bet_order_bet_amount'],
                             'sum', start_time, end_time, None, 0)
    lose_user_pool = user_filter.get_user_pool()
    dynamic_target_users_dct = dict(
        bet_user_pool=bet_user_pool,
        profit_user_pool=profit_user_pool,
        lose_user_pool=lose_user_pool
    )
    return dynamic_target_users_dct
